/*
**    Copyright (C) 2003-2011 Institute for Systems Biology
**                            Seattle, Washington, USA.
**
**    This library is free software; you can redistribute it and/or
**    modify it under the terms of the GNU Lesser General Public
**    License as published by the Free Software Foundation; either
**    version 3 of the License, or (at your option) any later version.
**
**    This library is distributed in the hope that it will be useful,
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
**    Lesser General Public License for more details.
**
**    You should have received a copy of the GNU Lesser General Public
**    License along with this library; if not, write to the Free Software
**    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
*/

package org.systemsbiology.util;


import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

/**
 * Author: anorberg
 * Created on: Nov 9, 2010
 */

/**
 * Filter class that represents a set of filters (a HashSet, specifically; it plans to hash by object handle)
 * and accepts elements only if they pass all of them.
 * @param <T> Element type for items to be filtered.
 */
public class ConjunctionFilter<T>  extends HashSet<Filter<T>> implements Filter<T> {

	private static final long serialVersionUID = 5796393121557401817L;

	/**
	 * Constructs a ConjunctionFilter containing no filters.
	 */
	public ConjunctionFilter(){
        super();
    }

	/**
	 * Constructs a ConjunctionFilter, containing a set of filters specified via an Iterator.
	 * @param startingSet Iterator that yields a sequence of filters to be used.
	 */
    public ConjunctionFilter(Iterator<? extends Filter<T>> startingSet){
        super();
        while(startingSet.hasNext()){
            add(startingSet.next());
        }
    }

    /**
     * Constructs a ConjunctionFilter, containing a Collection of filters. The contents of this
     * collection are copied; the collection is neither modified nor stored, so subsequent
     * modifications will have no effect on the ConjunctionFilter.
     * @param startingSet Collection of filters to be used.
     */
    public ConjunctionFilter(Collection<? extends Filter<T>> startingSet){
        super(startingSet);
    }

    /**
     * Constructs a ConjunctionFilter, containing filters specified in an array. The
     * contents of this array are copied; the array itself is neither modified nor stored, so
     * subsequent modifications to the array will have no effect on the ConjunctionFilter.
     * @param startingSet Array of filters to be used.
     */
    public ConjunctionFilter(Filter<T>[] startingSet){
        super(Arrays.asList(startingSet));
    }

    /**
     * Accepts an element if and only if all filters specified in the ConjunctionFilter allow
     * it. It will run filters in no guaranteed order until either every filter has been
     * run, or any filter returns false. (A filter is therefore not guaranteed to be
     * run on any given element that is rejected due to this early-out behavior.) If all filters
     * are exhausted without encounering a false result for their <code>accept</code> methods,
     * this method returns true; otherwise, it returns false.
     * <p>
     * A ConjunctionFilter with no elements will always return true in this method, because
     * there are no filters to reject any element.
     */
    public boolean accept(T item){
        for(Filter<T> foo : this){
            if(!foo.accept(item)){return false;}
        }
        return true;
    }

}
